import { isFunction } from 'lodash-es'
import { computed, provide, reactive, ref, nextTick, unref } from 'vue'
import { useToggle } from '@vueuse/core'
import { useState } from './state'
import { ElMessage, ElLoading } from 'element-plus'

/**
 * useBasePage
 * @param {{
 * title?: string,
 * addTitle?: string,
 * updateTitle?: string,
 * viewTitle?: string,
 * injectKey?: string,
 * mergeBasePageInfo?: Record<string, unknown>,
 * showSubmitMessage?: boolean,
 * successSubmitMessage?: string,
 * submit?: (opFlag: boolean) => boolean | void,
 * back?: (opFlag: boolean) => boolean | void
 * }} opts
 * @returns
*/
export const useBasePage = (opts = {}) => {
    const {
        title = '',
        addTitle,
        updateTitle,
        viewTitle,
        injectKey = 'BasePageInjectKey',
        mergeBasePageInfo = {},
        // submit
        showSubmitMessage = true,
        successSubmitMessage = `保存成功`,
        submit,
        // back
        back
    } = opts

    const [isShowDetail, toggleDetail] = useToggle(false)

    const {
        state: opFlag,
        setState: setOpFlag,
        resetState: resetOpFlag
    } = useState('')

    const detailRef = ref()

    const {
        state: customTitle,
        setState: setCustomTitle,
        resetState: resetCustomTitle
    } = useState(opts.customTitle)

    const computedTitle = computed(() => {
        if (customTitle.value) return customTitle.value
        switch (opFlag.value) {
            case 'add':
                return addTitle ? addTitle : `${title}-新增`
            case 'update':
                return updateTitle ? updateTitle : `${title}-编辑`
            case 'view':
                return viewTitle ? viewTitle : `${title}-查看`
            default:
                return title
        }
    })

    const basePageInfo = reactive({
        title: computedTitle,
        showDetail: isShowDetail,
        onDetailSubmit: async () => {
            const loading = ElLoading.service()
            try {
                if (isFunction(submit)) {
                    const needReturn = await submit(opFlag.value)
                    if (typeof needReturn === 'boolean' && needReturn === false) return
                }
                toggleDetail(false)
                showSubmitMessage && ElMessage.success(successSubmitMessage)
                resetOpFlag()
            } catch (error) {
                defaultCatchError(error)
            } finally {
                loading.close()
            }
        },
        onDetailBack: async () => {
            if (isFunction(back)) {
                const needReturn = await back(opFlag.value)
                if (typeof needReturn === 'boolean' && needReturn === false) return
            }

            toggleDetail(false)
            resetOpFlag()
        },
        showDetailOperate: computed(() => opFlag.value === 'view' ? false : true),
        ...mergeBasePageInfo
    })

    const openDetail = async (callback = () => {}) => {
        setOpFlag('update')
        toggleDetail(true)
        await nextTick()
        callback(context)
    }

    const _handleDetail = async row => {
        toggleDetail(true)
        await nextTick()
        unref(detailRef).init(opFlag.value, row)
    }

    const detailAdd = async row => {
        setOpFlag('add')
        _handleDetail(row)
    }
    const detailUpdate = async row => {
        setOpFlag('update')
        _handleDetail(row)
    }
    const detailView = async row => {
        setOpFlag('view')
        _handleDetail(row)
    }

    const context = {
        basePageInfo,
        openDetail,
        setCustomTitle,
        resetCustomTitle,
        opFlag,
        setOpFlag,
        resetOpFlag,
        isShowDetail,
        toggleDetail,
        detailRef,
        detailAdd,
        detailUpdate,
        detailView
    }

    injectKey && provide(injectKey, context)

    return context
}